package jee.boot.entity.auth;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Lists;
import jee.boot.common.annotation.Column;
import jee.boot.common.annotation.Table;
import jee.boot.common.annotation.Transient;
import jee.boot.common.basic.TreeEntity;
import jee.boot.common.basic.interceptor.impl.DefaultPreInsertInterceptor;
import jee.boot.common.basic.interceptor.impl.DefaultPreQueryInterceptor;
import jee.boot.common.basic.interceptor.impl.DefaultPreUpdateInterceptor;
import jee.boot.common.utils.JsonMapper;
import jee.boot.common.utils.StringUtils;
import jee.boot.entity.system.I18n;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 资源
 */
@Table(name = "st_resource")
public class Resource extends TreeEntity<Resource> {
    private static final long serialVersionUID = 1L;
    @Column(name = "parent_id", data = {"parent.id", "parent.name", "parent.title"})
    private Resource parent; // 父级编号
    private String icon; // 图标
    private String type; // 菜单/按钮/请求
    private String title; // 标题
    private String permission; // 权限标识()
    private String category;// app,web,都有
    /**
     * 资源类别
     */
    @Column(name = "st_resource_category")
    private String resourceCategory;//字典：DIC_SYS_ResourceType_*

    /**
     * 元数据
     */
    @Column(name = "st_meta")
    private String metaJson;//文本,该字段为前端准备的元数据字段,暂定长度为2000,如后期长度不够可能需要扩容

    @Transient
    private Map<String, Object> meta;
    /**
     * 父类节点ID
     */
    @Column(name = "st_super_id", data = {"superResource.id", "superResource.no", "superResource.code", "superResource.name", "superResource.desc", "superResource.type"})
    private Resource superResource;//引用：ST_RESOURCE(只引用ST_RESOURCE_TYPE = 'DIC_SYS_ResourceType_RT00'的虚拟资源)，当虚拟资源被授权时视为该虚拟资源的所有子类资源一并被授权
    /**
     * request类型的资源对应的数据权限规则
     */
    @Transient
    private List<RowSet> rowSetList = Lists.newArrayList();

    /**
     * 优先级
     */
    @Transient
    private Integer priority;

    /**
     * 一级叶子节点的数量
     */
    @Column(ignoreAlias = true, name = "(select count(1) from st_resource child where child.parent_id=a.id)", action = Column.Action.QUERY)
    private Integer childNum = 0;
    /**
     * 国际语言代码
     */
    private String i18nCode;
    /**
     * 国际语言
     */
    @Column(action = Column.Action.QUERY, key = "code", name = "i18n_code", data = {"i18n.id", "i18n.code", "i18n.label"}, extraConditions = {"i18n.language=#{language}"})
    private I18n i18n;

    public Resource() {
        super();
    }

    public Resource(String id) {
        super(id);
    }

    public Resource(String id, String type) {
        super(id);
        this.type = type;
    }

    public Resource getParent() {
        return parent;
    }

    public void setParent(Resource parent) {
        this.parent = parent;
    }

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }


    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getPermission() {
        return permission;
    }

    public void setPermission(String permission) {
        this.permission = permission;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getResourceCategory() {
        return resourceCategory;
    }

    public void setResourceCategory(String resourceCategory) {
        this.resourceCategory = resourceCategory;
    }

    @JsonIgnore
    public String getMetaJson() {
        return metaJson;
    }

    public void setMetaJson(String metaJson) {
        this.metaJson = metaJson;
    }

    public Map<String, Object> getMeta() {
        if (StringUtils.isNotBlank(metaJson)) {
            meta = JsonMapper.fromJsonString(metaJson, Map.class);
        }
        return meta;
    }

    public void setMeta(Map<String, Object> meta) {
        if (meta != null) {
            this.metaJson = JsonMapper.toJsonString(meta);
        }
        this.meta = meta;
    }

    public Resource getSuperResource() {
        return superResource;
    }

    public void setSuperResource(Resource superResource) {
        this.superResource = superResource;
    }

    public List<RowSet> getRowSetList() {
        return rowSetList;
    }

    public void setRowSetList(List<RowSet> rowSetList) {
        this.rowSetList = rowSetList;
    }

    public Integer getPriority() {
        return priority;
    }

    public void setPriority(Integer priority) {
        this.priority = priority;
    }

    public Integer getChildNum() {
        return childNum;
    }

    public void setChildNum(Integer childNum) {
        this.childNum = childNum;
    }

    public String getI18nCode() {
        return i18nCode;
    }

    public void setI18nCode(String i18nCode) {
        this.i18nCode = i18nCode;
    }

    public I18n getI18n() {
        return i18n;
    }

    public void setI18n(I18n i18n) {
        this.i18n = i18n;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Resource)) return false;
        if (!super.equals(o)) return false;
        Resource resource = (Resource) o;
        return Objects.equals(getId(), resource.getId());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getId());
    }

    @Override
    public void preInsert() {
        new DefaultPreInsertInterceptor().execute(this);
    }

    @Override
    public void preUpdate() {
        new DefaultPreUpdateInterceptor().execute(this);
    }

    @Override
    public void preQuery() {
        new DefaultPreQueryInterceptor().execute(this);
    }
}